/*
    Author: Vsevolod (AKA Sebastian) Mountaniol
*/

#include "updater.w.h"
#include "updater.h"
#include "updater.errors.h"
#include "updater.w.string.h"
#include "updater.w.memory.h"
#include "updater.w.file.h"
#include "updater.parser.h"




#define RUN_TROUGH_SPACE(c)	while(isspace(*c)) c++;

#if 0
/* TODO: Change to a enum */
enum xml_enum TagToInt(CHAR *str)
{
    ENTRY();

    if (0 == w_strncasecmp("file", str, 4))
    {
        RETURN(P_FILE_OPEN);        
    }

    if (! w_strncasecmp("dir", str, 3))
    {
        RETURN(P_DIR_OPEN);        
    }

    if (! w_strncasecmp("command", str, 7))
    {
        RETURN(P_COMMAND_OPEN);        
    }

    if (! w_strncasecmp("set", str, 3))
    {
        RETURN(P_SET_OPEN);        
    }

    if (! w_strncasecmp("path", str, 4))
    {
        RETURN(P_PATH_OPEN);        
    }
    if (! w_strncasecmp("perm", str, 4))
    {
        RETURN(P_PERM_OPEN);        
    }

    if (! w_strncasecmp("src", str, 3))
    {
        RETURN(P_SRC_OPEN);        
    }
    if (! w_strncasecmp("dst", str, 3))
    {
        RETURN(P_SET_OPEN);        
    }

    if (! w_strncasecmp("exec", str, 4))
    {
        RETURN(P_SET_OPEN);        
    }

    RETURN(-1);
}

/* Process the <file> tag */
INT process_file_tag(ucore_t *ps_ucore)
{
    /* tag_t tag = P_NONE; */

    /* Read until */
    ENTRY();

    RETURN(OK);
}

/* Process the <dir> tag */
INT process_dir_tag(ucore_t *ps_ucore)
{
    ENTRY();
    RETURN(OK);
}

/* Process the <command> tag */
INT process_command_tag(ucore_t *ps_ucore)
{
    ENTRY();
    RETURN(OK);
}


/* 	Tag it is something like <word> - opening tag,
	OR </> or </word> - closing tag.
	The main form of closing rag is </>
	User may use </word>, but "word" will be ignored.
*/
INT ExtractTagEntry(CHAR * str, tag_t * p_tag)
{
    CHAR * pc_begin; 
    CHAR *pc_end;

    CHAR c_closing = 0;
    CHAR *buf;
    buf = (CHAR *) w_malloc(sizeof(CHAR) * 16);
    
    if (NULL == buf)
    {
	    DE("Can't allocate buffer\n");
	    RETURN(-1);
    }
    

    ENTRY();

    pc_begin = pc_end = str;

    while ( '<' != *str && '\0' != *str )
    {
        DD("first while : %c \n", *str);
        if ('#' == *str) 
        {
            /* This is commnted line! */
		w_free(buf);
            RETURN(P_COMMENT);
        }
        str++;
    }

    /* Jump to next char after '<' */
    str++;

    /* If it is end of the string - error */
    if ('\0' == *str)
    {
        *p_tag = P_EMPTY;
	w_free(buf);
        RETURN(OK);
    }

    /* Is it closing tag?*/

    if ('/' == *str)
    {
        c_closing = 1;
        str++;
    }

    /* Ok, now extract the tag name */

    
	/* split blanks */
    while (w_isblank(*str))
    {
        str++;
    }

    /* All right, it is begin of the tag name */
    pc_begin = str;

    /* run on the world */
    while ( '>' != *str )
    { 
        str++;
    }

    /* Overrun the end of tag */
    pc_end = str - 1;

    if (pc_end <= pc_begin)
    {
        /* It is an error, isn't it?  */
    } 
    w_memcpy(buf, pc_begin, (pc_end-pc_begin) + 1 );
    buf[(pc_end-pc_begin)+1] = '\0';

    *p_tag = TagToInt(buf);

        /* it is a <close tag */
        /* If it is the close tag then I just increment the value of the i_tag. It is the order of the tag numeration: */
        /* tag_open  = n */
        /* tag_close = n+1 */
        /* See define of tag numeration (TODO: in file update.parser.h) */

    /* Move the pointer to the end of tag */
    *p_tag += c_closing;

    w_free(buf);
    RETURN(OK);
}

#define PARSER_BUF_SIZE 4096

INT ParseSpec(ucore_t * ps_ucore, CHAR * config_name)
{
    INT rv;
    CHAR *  buf;
    
    tag_t /* enum tag_enum */ context_tag;
    ENTRY();

    buf = w_malloc(PARSER_BUF_SIZE);
    
    if (NULL == buf)
    {
	    DE("Can't allocate buffer\n");
	    RETURN(-1);
			    
    } 
    /*  Standart paranoia */
    if (NULL == ps_ucore || NULL == config_name)
    { 
        DE("Wrong arg\n");
		w_free(buf);
        RETURN(-EARGUMENT);
    }


    /* 1. Read until first tag. */

    /* Tag is something like <word> */
    /* When a tag is found the parser enters into the tag context. */
    /* It is recursive process. But instead of recursion I use simple stack to keep the states. */

    /* The parser is simple. There is number of "mine" tags, as <file>, <dir>, <command> */
    /* The main tags are defined. No surprises. */
    /* Inside of the main tags may be secondary tags, also predefined. */

    ps_ucore->file_in = w_open(config_name, W_O_RDONLY);

    if( NULL == ps_ucore->file_in )
    {
        DE("Can't open file %s\n", config_name);
		w_free(buf);
        RETURN( - EFILEOPEN );
    } 

    while (NULL != fgets(buf, 2048, ps_ucore->file_in))
    {
        rv = ExtractTagEntry(buf, &context_tag);
        if (OK != rv)
        {
		DE("Parsing error\n");
		w_free(buf);
		RETURN(rv);
         }

        /* Enter to tag context parsing  */

        if (P_COMMAND_OPEN == context_tag)
         {
            /* Parse command tag */
            rv = process_command_tag(ps_ucore);
        }

        if (P_DIR_OPEN == context_tag)
        {
            /* Parse dir tag */
            rv = process_dir_tag(ps_ucore);
         }

        if (P_FILE_OPEN == context_tag)
        {
            /* Parse command tag */
            rv = process_file_tag(ps_ucore);
        } 

        context_tag = P_NONE;
    } 

    rv = fclose(ps_ucore->file_in);

    if (rv)
    {
        PERROR("Error on spec closing: ");
	    w_free(buf);
        RETURN( - ECLOSE );
    } 
    w_free(buf);
    RETURN(OK);
}

#endif /*# 0 #*/
